﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BlackBBS.Models.Data;
using BlackBBS.Extensions;
using System.IO;
using System.Diagnostics;
using BlackBBS.Enums;

namespace BlackBBS.Menus
{
    public class ExtPrograms : MenuBase
    {
        public IList<ExtProgram> ExtProgams { get; set; }

        public ExtPrograms()
        {
        }

        public override void Init()
        {
            base.Init();

            // TODO; get from Repository
            this.ExtProgams = new List<ExtProgram>();
            this.ExtProgams.Add(new ExtProgram
            {
                Id = 1,
                MenuKey = "l",
                BatchFile = @"C:\bbs\doors\lord\start.bat",
                Description = "Legend Of The Red Dragon",
                Name = "L.O.R.D.",                   
                Created = DateTime.Now
            });
            this.ExtProgams.Add(new ExtProgram
            {
                Id = 1,
                MenuKey = "a",
                BatchFile = @"C:\bbs\doors\ab2\start.bat",
                Description = "Arrowbridge II",
                Name = "AB2",
                Created = DateTime.Now
            });
            this.ExtProgams.Add(new ExtProgram
            {
                Id = 1,
                MenuKey = "g",
                BatchFile = @"C:\bbs\doors\gwar\war.bat",
                Description = "Global War",
                Name = "GW",
                Created = DateTime.Now
            });
        }

        public override void SendMenu()
        {
            var handled = false;
            while (!handled)
            {
                this.Connection.SetCurrentArea(Area.ExtProgramMenu);
                this.Connection.ClearScreen();
                this.Connection.SendFile("DOORS.ANS");
                handled = this.HandleResponse(this.Connection.SendScript("DOORS.MNU"));
            }
        }

        public bool HandleResponse(Dictionary<string, string> response)
        {
            if (response == null || response.Count == 0)
            {
                return false;
            }

            var key = (response.First().Key ?? string.Empty).ToLower();
            var value = (response.First().Value ?? string.Empty).ToLower();

            if (value.Equals("q"))
            {
                var main = new BlackBBS.Menus.Main
                {
                    Connection = this.Connection
                };
                main.Init();
                main.SendMenu();
                return true;
            }
            var foundExtProgram = this.ExtProgams.Where(x => x.MenuKey.Equals(value, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();
            if (foundExtProgram != null)
            {
                this.DoExtProgram(foundExtProgram);
                this.Connection.Pause(1, 500);
                return false;
            }
            else
            {
                this.Connection.SendInvalidKey(value);
            }
            return false;
        }

        void DoExtProgram(ExtProgram extProgram)
        {
            try
            {
                this.Connection.SetCurrentArea(Area.ExtProgram);

                var nodePath = this.Connection.ServerSettings.CurrentNodeExtProgramsFullPath(this.Connection.Node);

                this.BuildDropFile(nodePath);

                string nf = Path.Combine(this.Connection.ServerSettings.CurrentNodeExtProgramsFullPath(this.Connection.Node), "nf.bat");
                Process p = new Process();
                p.EnableRaisingEvents = false;
                p.StartInfo.FileName = Path.Combine(nodePath, "nf.bat");
                p.StartInfo.Arguments = string.Format("/n{0} /h{1} {2} {0}", this.Connection.Node, this.Connection.ClientSocketHandle, extProgram.BatchFile);
                p.StartInfo.WorkingDirectory = nodePath;
                p.StartInfo.UseShellExecute = false;
                p.Start();
                p.WaitForExit();
                p.Close();

                this.CleanUpDropFiles(nodePath);

            }
            catch (Exception ex)
            {
                this.LogException(ex);
            }
        }

        void CleanUpDropFiles(string path)
        {
            // TODO; 
        }

        void BuildDropFile(string path)
        {
            //http://goldfndr.home.mindspring.com/dropfile/

            var address = this.Connection.ClientRemoteEndPoint.ToString();
            var port = address.Substring(address.IndexOf(":") + 1, (address.Length - (address.IndexOf(":") + 1)));

            var minutesRemaining = this.Connection.Session.Expires.DateDiffInMinutes(DateTime.Now);

            using (StreamWriter sw = new StreamWriter(Path.Combine(path, "DOOR32.SYS")))
            {
                sw.WriteLine(1);
                sw.WriteLine("1");
                sw.WriteLine(38400);
                sw.WriteLine(this.Connection.ServerSettings.Version);
                sw.WriteLine(this.Connection.Session.User.Id);
                sw.WriteLine(this.Connection.Session.User.FullName);
                sw.WriteLine(this.Connection.Session.User.Login);
                sw.WriteLine(this.Connection.Session.User.Group.Level); 
                sw.WriteLine(minutesRemaining); 
                sw.WriteLine(1); // use ANSI
                sw.WriteLine(this.Connection.Node);
            }

            using (StreamWriter sw = new StreamWriter(Path.Combine(path,  string.Format("DORINFO{0}.DEF", this.Connection.Node))))
            {
                sw.WriteLine(string.Format("Node{0}",  this.Connection.Node.ToString("00"))); // Node Name
                sw.WriteLine(this.Connection.ServerSettings.SysOp.Firstname); // Sysop First name
                sw.WriteLine(this.Connection.ServerSettings.SysOp.Lastname); // Sysop Last name
                sw.WriteLine("COM1:"); // Com port
                sw.WriteLine(38400); // Baud Rate
                sw.WriteLine(0); // Networked
                sw.WriteLine(this.Connection.Session.User.Firstname); // User First name
                sw.WriteLine(this.Connection.Session.User.Lastname); // User Last name
                sw.WriteLine(this.Connection.Session.User.Address.City); // User City
                sw.WriteLine(1); // ANSI Terminal Type
                sw.WriteLine(this.Connection.Session.User.Group.Level);  // Security Level
                sw.WriteLine(minutesRemaining.TakeLess(546));  // Minutes Remaining (max 546)
                sw.WriteLine(-1);  // Use Fossil
            }

            using (StreamWriter sw = new StreamWriter(Path.Combine(path, "DOOR.SYS")))
            {
                sw.WriteLine("COM1:");
                sw.WriteLine("38400");
                sw.WriteLine("8");
                sw.WriteLine(this.Connection.Session.Node);
                sw.WriteLine("38400");
                sw.WriteLine("Y");
                sw.WriteLine("Y");
                sw.WriteLine("Y");
                sw.WriteLine("Y");
                sw.WriteLine(this.Connection.Session.User.FullName); 
                sw.WriteLine(this.Connection.Session.User.Address.CallingFrom);
                sw.WriteLine(this.Connection.Session.User.Phone1);
                sw.WriteLine(this.Connection.Session.User.Phone2);
                sw.WriteLine("PASSWORD");
                sw.WriteLine(this.Connection.Session.User.Group.Level);
                sw.WriteLine(this.Connection.Session.User.LoginTotal);
                sw.WriteLine(this.Connection.Session.User.LoginLast.HasValue ? this.Connection.Session.User.LoginLast.Value.ToString("MM/dd/yyyy") : string.Empty);
                sw.WriteLine(minutesRemaining*60);
                sw.WriteLine(minutesRemaining);
                sw.WriteLine("GR");
                sw.WriteLine(this.Connection.Session.User.Preferences.TermHeight);
                sw.WriteLine(this.Connection.Session.User.Preferences.ExpertMode ? "Y" : "N");  
                sw.WriteLine(this.Connection.Session.RegisteredMsgAreas);
                sw.WriteLine(this.Connection.Session.MsgExitedToExtProgramFrom);
                sw.WriteLine(this.Connection.Session.User.Expires.HasValue ? this.Connection.Session.User.Expires.Value.ToString("MM/dd/yyyy") : string.Empty);
                sw.WriteLine(this.Connection.Session.User.Id);
                sw.WriteLine("Y");
                sw.WriteLine(this.Connection.Session.User.TotalFilesUploaded);
                sw.WriteLine(this.Connection.Session.User.TotalFilesDownloaded);
                sw.WriteLine(0); // Daily Download "K" total
                sw.WriteLine(999999); // Daily Download Max. "K" Limit
                sw.WriteLine(this.Connection.Session.User.Birthday.HasValue ? this.Connection.Session.User.Birthday.Value.ToString("MM/dd/yyyy") : string.Empty);
                sw.WriteLine(path);
                sw.WriteLine(this.Connection.ServerSettings.BBSRootPath);
                sw.WriteLine(this.Connection.ServerSettings.SysOp.Firstname);
                sw.WriteLine(this.Connection.ServerSettings.SysOp.Login);
                sw.WriteLine("00:05"); // Event Time
                sw.WriteLine("Y");
                sw.WriteLine("N");
                sw.WriteLine("Y");
                sw.WriteLine("14");
                sw.WriteLine(this.Connection.Session.User.TimebankBalance);
                sw.WriteLine(this.Connection.Session.User.LastNewFilesScan.HasValue ? this.Connection.Session.User.LastNewFilesScan.Value.ToString("MM/dd/yyyy") : string.Empty);
                sw.WriteLine(this.Connection.Session.Created.ToString("hh:mm"));
                sw.WriteLine("07:30"); // time of last call
                sw.WriteLine(6); //Maximum daily files available 
                sw.WriteLine(3); //Files d/led so far today      
                sw.WriteLine(0); //Total "K" Bytes Uploaded      
                sw.WriteLine(0); //Total "K" Bytes Downloaded    
                sw.WriteLine(this.Connection.Session.User.SysopNote); 
                sw.WriteLine(this.Connection.Session.User.TotalExtProgramsOpened);
                sw.WriteLine(99999); //Total Messages Left           
            }
        }

    }
}
